<?php
declare (strict_types=1);

namespace app\exam\logic\admin;

use app\common\exception\LogicException;
use app\common\helper\util\Page;
use app\exam\model\admin\ModuleSpecialTopic as ModuleSpecialTopicModel;
use app\exam\model\admin\{QuestionTopic, QuestionBank};
use think\annotation\Inject;

/**
 * Class ModuleSpecialTopic
 *
 * @package app\exam\logic\admin
 */
class ModuleSpecialTopic extends ModuleSpecialTopicModel
{
    /**
     * @Inject()
     *
     * @var QuestionTopic
     */
    protected $questionTopicModel;

    /**
     * @Inject()
     *
     * @var QuestionPoint
     */
    protected $questionPointLogic;

    /**
     * @Inject()
     *
     * @var \app\exam\model\admin\ModuleSpecial
     */
    protected $moduleSpecialModel;

    /**
     * 储存专项的id数据
     *
     * @var array
     */
    protected $specialTopids = [];

    /**
     * 获取数据
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/2/1
     *
     * @param int $specialId
     * @return \think\Paginator
     * @throws \think\db\exception\DbException
     */
    public function getList(int $specialId)
    {
        return $this->where('special_id', $specialId)->with('topic')->paginate(Page::listRows());
    }

    /**
     * 获取选择的试题列表
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/2/3
     *
     * @param array $map
     * @param int   $specialId
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getChooseList(int $specialId, array $map = [])
    {
        // 专项分类
        $category = $this->moduleSpecialModel->whereId($specialId)->value('category');
        // 对应分类题库
        $questionBankLogic = app(QuestionBank::class);
        $binkIds           = $questionBankLogic->where('category', $category)->column('id');
        $map[]             = ['question_bank_id', 'IN', $binkIds];
        // 相同专项试题不重复，获取同一专项所有ID
        $specialIds = $this->getIncludeSpecial($specialId);
        // 查询试题列表
        return $this->questionTopicModel
            ->where($map)
            ->with(['difficultyTitle'])
            ->withCount(['checked' => function($query) use ($specialIds)
            {
                $query->where('special_id', 'IN', $specialIds);
            }])
            ->paginate(Page::listRows())
            ->each(function ($item) {
                $item->checked = !!$item->checked_count;
            })->append(['question_type_text', 'point_str']);
    }

    /**
     * 新增试题
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/2/3
     *
     * @param int   $specialId
     * @param array $topics
     * @throws \Exception
     */
    public function createModuleSpecialTopic(int $specialId, array $topics)
    {
        $saveAll = [];
        foreach ($topics as $topic) {
            $saveAll[] = [
                'special_id' => $specialId,
                'topic_id'   => $topic
            ];
        }

        $ret = $this->replace()->saveAll($saveAll);

        if (!$ret) {
            throw new LogicException('新增失败');
        }

        // 更新数量
        $num = count($ret);
        $this->moduleSpecialModel->where('id', $specialId)->inc('topic_count', $num)->update();
    }

    /**
     * 移除试题
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/2/3
     *
     * @param int    $specialId
     * @param string $ids
     */
    public function deleteModuleSpecialTopic(int $specialId, string $ids)
    {
        $res = $this->whereIn('id', $ids)->selectOrFail()->delete();
        if (!$res) {
            throw new LogicException('移除失败');
        }

        $num = count(explode(',', $ids));

        $this->moduleSpecialModel->where('id', $specialId)->dec('topic_count', $num)->update();
    }

    private function getIncludeSpecial(int $specialId)
    {
        if (!isset($this->specialTopids[$specialId])) {
            $topid = $this->getSpecialTopId($specialId);

            $ids = $this->getAllSpecialIds($topid);

            $this->specialTopids[$specialId] = $ids;
        }

        return $this->specialTopids[$specialId];
    }

    /**
     * 获取顶级专项id
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/14
     *
     * @param int $specialId
     * @return int
     */
    private function getSpecialTopId(int $specialId)
    {
        $pid = $this->moduleSpecialModel->where('id', $specialId)->value('pid');
        if ($pid != 0) {
            return $this->getSpecialTopId($pid);
        }

        return $specialId;
    }

    private function getAllSpecialIds(int $specialId)
    {
        static $specialIds;
        $specialIds[] = $specialId;
        $ids          = $this->moduleSpecialModel->where('pid', $specialId)->column('id');
        foreach ($ids as $id) {
            $this->getAllSpecialIds($id);
        }

        return $specialIds;
    }

}